#pragma once

#include "refine/information_source.h"
#include "types.h"

namespace xml { class stream; }

namespace trm {

struct param {
	int reference_frame_pitch;
	int downsample;

	bool optic_flow;
	//if optic_flow is true
	int max_motion;
	int tracker_size;

	bool mincut;
	int mincut_pyramid_levels;
	mincut::information_source mincut_information_source;
	int mincut_max_motion;
	int mincut_max_link_distance;
	int mincut_link_count;
	float mincut_aspect;
	int mincut_interframe_max_link_distance;
	int mincut_interframe_link_count;
	bool mincut_antialiasing;
	int mincut_antialiasing_levels_exp;

/*	bool entropic_tracker;
	int entropic_best_move_iter_num;
	int entropic_move_radius;
	int entropic_band_radius;
	float entropic_unambig_thr;
	float entropic_alpha;
	bool entropic_sqrt_control;
	bool entropic_safe_time_step;*/

	bool refine_mask;
	refine::information_source refine_information_source;
	int refine_window_half_size;
	bool refine_auto;
	float refine_enough_statistics;
	refine::preference refine_preference;

	bool refine2_mask;
	int refine2_max_motion;
	int refine2_max_level;

/*	bool refine3_mask;
	refine::information_source refine3_information_source;
	float refine3_enough_statistics;
	refine::preference refine3_preference;*/

	int dilation_erosion;
	int wool_removal;

	bool decrease_mask_freedom;
	int decrease_freedom_degrees;
	bool decrease_smooth_contour;
	int decrease_iterations;
	float decrease_nodes_traction;
	float decrease_tangents_traction;
	
	smooth_mask_method smooth_mask;
	//if smooth_mask is true
	int smooth_window_half_size;
	int smooth_passes_num;
	int smooth_max_condition_number;
	//int smooth_fore_depth;
	//int smooth_back_depth;
	//float smooth_sharpness;
	//float smooth_noisiness;
	bool smooth_decorative;

	void set_default_values();
	void put_within_the_limits();
	int mincut_total_window_pixels() const;
	int mincut_total_interframe_window_pixels() const;
	bool interframe_mincut() const;
	bool mincut_pyramid() const;
	bool mincut_and_antialiasing() const;
	int refine_total_window_pixels() const;
	bool smooth_off() const;
	//bool smooth_b() const;
	//bool smooth_depend_on_max_condition_number() const;
	//bool smooth_has_depth() const;
	int smooth_total_window_pixels() const;

	xml::stream & serialize(xml::stream & s);
};

extern param const default_param;

bool operator == (param const & lhs, param const & rhs);
inline bool operator != (param const & lhs, param const & rhs)
	{ return !(lhs == rhs); }

inline int param::mincut_total_window_pixels() const
	{ return (2*mincut_max_link_distance+1)*(2*mincut_max_link_distance+1); }

inline int param::mincut_total_interframe_window_pixels() const
	{ return (2*mincut_interframe_max_link_distance+1)*(2*mincut_interframe_max_link_distance+1); }

inline bool param::interframe_mincut() const
	{ return mincut && mincut_information_source == mincut::source_both; }

inline bool param::mincut_pyramid() const
	{ return mincut && mincut_pyramid_levels > 0; }

inline bool param::mincut_and_antialiasing() const
	{ return mincut && mincut_antialiasing && !smooth_mask; }

inline int param::refine_total_window_pixels() const
	{ return (2*refine_window_half_size+1)*(2*refine_window_half_size+1); }

inline bool param::smooth_off() const
	{ return smooth_mask == smooth_mask_off; }

//inline bool param::smooth_b() const
//	{ return smooth_mask == smooth_mask_B; }

//inline bool param::smooth_depend_on_max_condition_number() const
//	{ return smooth_mask != smooth_mask_B && smooth_mask != smooth_mask_E; }

//inline bool param::smooth_has_depth() const
//	{ return smooth_mask != smooth_mask_equal_spheres && smooth_mask != smooth_mask_equal_ellipses && smooth_mask != smooth_mask_different_ellipses; }

inline int param::smooth_total_window_pixels() const
	{ return (2*smooth_window_half_size+1)*(2*smooth_window_half_size+1); }

inline xml::stream & operator || (xml::stream & s, param & p)
	{ return p.serialize(s); }

} //namespace trm
